package mware_lib;

import java.io.IOException;



import java.net.InetAddress;
import java.net.UnknownHostException;

import branch_access.Manager;
import branch_access.ManagerProxy;
import cash_access.Account;
import cash_access.AccountProxy;
import mware_lib.namensdienst.communication.Client;
import mware_lib.namensdienst.messages.*;

public class LokalerNamensDienst extends NameService {

	private Client client;

	private String localHost;
	private int accountSkeletonPort = 55555;
	private int managerSkeletonPort = 55554;

	private int servicePort;
	private String serviceHost;

	private static ManagerSkeleton ms;
	private Manager bank;

	public LokalerNamensDienst(String serviceHost, int servicePort){
		this.serviceHost = serviceHost;
		this.servicePort = servicePort;

		//System.out.println("LokalerNamensDienst erstellt");

		try {
			localHost = InetAddress.getLocalHost().getHostAddress();
		} catch (UnknownHostException e) {
			throw new RemoteException(e.getClass().toString() + ": " + e.getMessage(), e);
		}
	}

	public void rebind(Object type, String id) {
		RebindMsg rebMsg;
		String rebindType = "";

		if(type != null){
			//erstelle neuen Eintrag

			int port = 0;
			if(type.getClass().getSuperclass().equals(Manager.class)){
				rebindType = "Manager";
				bank = (Manager) type;
				ms = new ManagerSkeleton(managerSkeletonPort, accountSkeletonPort, bank);
				Thread t = new Thread(ms);
				t.start();

				port = managerSkeletonPort;
				//System.out.println("Es hat sich eine Bank angemeldet.");
			}else if(type.getClass().getSuperclass().equals(Account.class)){
				rebindType = "Account";

				//System.out.println("ms: " + ms + "; id: " + id + "; type: " + type);

				ms.putAccountToTable(id, (Account)type);
				port = accountSkeletonPort;

			}

			rebMsg = new RebindMsg(id, localHost, port, rebindType);
		}else{
			//l�sche Eintrag

			ms.removeFromAccountTable(id);
			rebMsg = new RebindMsg(id, null, 0, null);
		}

		try {
			client = new Client(serviceHost, servicePort);
			client.send(rebMsg);
			
			RebindBackMsg rebBackMsg = (RebindBackMsg) client.receive();
			if(rebBackMsg != null && !rebBackMsg.isErfolgreich()){
				throw new RemoteException("Fehler Rebind, beim Entfernen: Konto garnicht vorhanden");
			}
			
			client.close();
		} catch (IOException e) {
			throw new RemoteException(e.getClass().toString() + ": " + e.getMessage(), e);
		} catch (ClassNotFoundException e) {
			throw new RemoteException(e.getClass().toString() + ": " + e.getMessage(), e);
		}
	}

	public Object resolve(String ID){

		System.out.println("-----> ID: " + ID);

		ResolveMsg resMsg = new ResolveMsg(ID);
		ResolveBackMsg returnMsg = null;

		try {
			client = new Client(serviceHost, servicePort);

			client.send(resMsg);
			//System.out.println("Cliend send() gemacht");

			returnMsg = (ResolveBackMsg)client.receive();

			client.close();

		} catch (UnknownHostException e) {
			throw new RemoteException(e.getClass().toString() + ": " + e.getMessage(), e);
		} catch (IOException e) {
			throw new RemoteException(e.getClass().toString() + ": " + e.getMessage(), e);
		} catch (ClassNotFoundException e) {
			throw new RemoteException(e.getClass().toString() + ": " + e.getMessage(), e);
		}

		if(returnMsg != null){

			if(returnMsg.getType() == null){
				throw new RemoteException("Fehler resolve: Gesuchte ID nicht vorhanden!");
			}else if(returnMsg.getType().equals("Account")){
				return new AccountProxy(returnMsg.getHost(), returnMsg.getPort(), ID);
			}else if(returnMsg.getType().equals("Manager")){
				//System.out.println("Es wurde ein Managerproxy erstellt");
				return new ManagerProxy(returnMsg.getHost(), returnMsg.getPort(), ID);
			}

		}else{
			System.out.println("LokalerNamensDienst.resolve: returnMsg = null -> Fehler");
		}

		return null;
	}

}
